home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / unzipsrc.zip / UNZIP.C < prev    next >
Text File  |  1993-04-16  |  24KB  |  1,086 lines

  1.  
  2. /*
  3.  * Copyright 1987, 1989 Samuel H. Smith;  All rights reserved
  4.  *
  5.  * This is a component of the ProDoor System.
  6.  * Do not distribute modified versions without my permission.
  7.  * Do not remove or alter this notice or any other copyright notice.
  8.  * If you use this in your own program you must distribute source code.
  9.  * Do not use any of this in a commercial product.
  10.  *
  11.  */
  12.  
  13. /*
  14.  * UnZip - A simple zipfile extract utility
  15.  *
  16.  */
  17.  
  18. #define version  "UnZip:  Zipfile Extract v1.1 of 03-08-89;  (C) 1989 S.H.Smith"
  19.  
  20. typedef unsigned char   byte;           /* code assumes UNSIGNED bytes */
  21. typedef long            longint;
  22. typedef unsigned        word;
  23. typedef char            boolean;
  24. #define STRSIZ          256
  25.  
  26. #include <stdio.h>
  27.         /* this is your standard header for all C compiles */
  28.  
  29. #include <stdlib.h>
  30.         /* this include defines various standard library prototypes */
  31.  
  32.  
  33. /*
  34.  * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
  35.  *
  36.  */
  37.  
  38.  
  39. /* ----------------------------------------------------------- */
  40. /*
  41.  * Zipfile layout declarations
  42.  *
  43.  */
  44.  
  45.    typedef longint       signature_type;
  46.  
  47.  
  48.    #define local_file_header_signature  0x04034b50L
  49.  
  50.  
  51.    typedef struct local_file_header {
  52.       word         version_needed_to_extract;
  53.       word         general_purpose_bit_flag;
  54.       word         compression_method;
  55.       word         last_mod_file_time;
  56.       word         last_mod_file_date;
  57.       longint      crc32;
  58.       longint      compressed_size;
  59.       longint      uncompressed_size;
  60.       word         filename_length;
  61.       word         extra_field_length;
  62.    } local_file_header;
  63.  
  64.  
  65.    #define central_file_header_signature  0x02014b50L
  66.  
  67.  
  68.    typedef struct central_directory_file_header {
  69.       word         version_made_by;
  70.       word         version_needed_to_extract;
  71.       word         general_purpose_bit_flag;
  72.       word         compression_method;
  73.       word         last_mod_file_time;
  74.       word         last_mod_file_date;
  75.       longint      crc32;
  76.       longint      compressed_size;
  77.       longint      uncompressed_size;
  78.       word         filename_length;
  79.       word         extra_field_length;
  80.       word         file_comment_length;
  81.       word         disk_number_start;
  82.       word         internal_file_attributes;
  83.       longint      external_file_attributes;
  84.       longint      relative_offset_local_header;
  85.    } central_directory_file_header;
  86.  
  87.  
  88.    #define end_central_dir_signature  0x06054b50L
  89.  
  90.  
  91.    typedef struct end_central_dir_record {
  92.       word         number_this_disk;
  93.       word         number_disk_with_start_central_directory;
  94.       word         total_entries_central_dir_on_this_disk;
  95.       word         total_entries_central_dir;
  96.       longint      size_central_directory;
  97.       longint      offset_start_central_directory;
  98.       word         zipfile_comment_length;
  99.    } end_central_dir_record;
  100.  
  101.  
  102.  
  103. /* ----------------------------------------------------------- */
  104. /*
  105.  * input file variables
  106.  *
  107.  */
  108.  
  109.    byte     inbuf[512];      /* input file buffer - any size is legal */
  110.    int      inpos;
  111.    int      incnt;
  112.    int      pc;
  113.    int      pcbits;
  114.    int      pcbitv;
  115.    boolean  zipeof;
  116.  
  117.    longint  csize;
  118.    longint  cusize;
  119.    int      cmethod;
  120.  
  121.    int      zipfd;
  122.    char     zipfn[STRSIZ];
  123.    local_file_header lrec;
  124.  
  125.  
  126.  
  127.  
  128. /* ----------------------------------------------------------- */
  129. /*
  130.  * output stream variables
  131.  *
  132.  */
  133.  
  134.    byte     outbuf[4096];   /* output file buffer for rle look-back -
  135.                                you can make this larger but the Expand()
  136.                                function requires the size to be at least
  137.                                4096 bytes */
  138.  
  139.    longint  outpos;         /* absolute position in outfile */
  140.    int      outcnt;         /* current position in outbuf */
  141.  
  142.    int      outfd;
  143.    char     filename[STRSIZ];
  144.    char     extra[STRSIZ];
  145.  
  146.  
  147.  
  148. /* ----------------------------------------------------------- */
  149. /*
  150.  * shrink/reduce working storage
  151.  *
  152.  */
  153.  
  154.    int      factor;
  155.    byte     followers[256][64];
  156.    byte     Slen[256];
  157.    int      ExState;
  158.    int      C;
  159.    int      V;
  160.    int      Len;
  161.  
  162.    #define max_bits      13
  163.    #define init_bits     9
  164.    #define hsize         8192
  165.    #define first_ent     257
  166.    #define clear         256
  167.  
  168.    typedef int  hsize_array_integer[hsize+1];
  169.    typedef byte hsize_array_byte[hsize+1];
  170.  
  171.    hsize_array_integer prefix_of;
  172.    hsize_array_byte    suffix_of;
  173.    hsize_array_byte    stack;
  174.  
  175.    int      cbits;
  176.    int      maxcode;
  177.    int      free_ent;
  178.    int      maxcodemax;
  179.    int      offset;
  180.    int      sizex;
  181.  
  182.  
  183. /* ============================================================= */
  184. /*
  185.  * Host operating system details
  186.  *
  187.  */
  188.  
  189. #include <io.h>
  190.         /* this include file defines
  191.                 struct ftime ...        (* file time/date stamp info *)
  192.                 int setftime (int handle, struct ftime *ftimep);
  193.  
  194.                 #define SEEK_CUR  1     (* lseek() modes *)
  195.                 #define SEEK_END  2
  196.                 #define SEEK_SET  0
  197.         */
  198.  
  199. #include <fcntl.h>
  200.         /* this include file defines
  201.                 #define O_BINARY        0x8000  (* no cr-lf translation *)
  202.            as used in the open() standard function */
  203.  
  204. #include <sys/stat.h>
  205.         /* this include file defines
  206.                 #define S_IREAD 0x0100  (* owner may read *)
  207.                 #define S_IWRITE 0x0080 (* owner may write *)
  208.            as used in the creat() standard function */
  209.  
  210.  
  211. #undef HIGH_LOW         /* change UNDEF to DEFINE if your processor stores
  212.                            the HIGH bytes before the LOW bytes in memory */
  213.  
  214. void         set_file_time(void)
  215.    /* set the output file date/time stamp according to information from
  216.       the zipfile directory record for this file */
  217. {
  218.    union {
  219.         struct ftime ft;
  220.         struct {
  221.             word ztime;
  222.             word zdate;
  223.         } zt;
  224.     } td;
  225.  
  226.    /* set output file date and time - this is optional and can be
  227.       deleted if your compiler does not easily support setftime() */
  228.  
  229.    td.zt.ztime = lrec.last_mod_file_time;
  230.    td.zt.zdate = lrec.last_mod_file_date;
  231.  
  232.    setftime(outfd,&td.ft);
  233. }
  234.  
  235.  
  236. int          create_output_file()
  237.    /* return non-0 if creat failed */
  238. {
  239.    /* create the output file with READ and WRITE permissions */
  240.    outfd = creat(filename,S_IWRITE|S_IREAD);
  241.    if (outfd < 1)
  242.    {
  243.       printf("Can't create output: %s\n",filename);
  244.       return 1;
  245.    }
  246.  
  247.    /* close the newly created file and reopen it in BINARY mode
  248.       to disable all CR/LF translations */
  249.    close(outfd);
  250.    outfd = open(filename,O_RDWR|O_BINARY);
  251.    return 0;
  252. }
  253.  
  254. int          open_input_file()
  255.    /* return non-0 if creat failed */
  256. {
  257.    /* open the zipfile for reading and in BINARY mode to prevent
  258.       cr/lf translation, which would corrupt the bitstreams */
  259.  
  260.    zipfd = open(zipfn,O_RDONLY|O_BINARY);
  261.    if (zipfd < 1) {
  262.       printf("Can't open input file: %s\n",zipfn);
  263.       return(1);
  264.    }
  265.    return 0;
  266. }
  267.  
  268.  
  269. #ifdef HIGH_LOW
  270.  
  271. void         swap_bytes(word *wordp)
  272.    /* convert intel style 'short int' variable to host format */
  273. {
  274.    char *charp = (char *)wordp;
  275.    char temp;
  276.  
  277.    temp = charp[0];
  278.    charp[0] = charp[1];
  279.    charp[1] = temp;
  280. }
  281.  
  282. void         swap_lbytes(longint *longp)
  283.    /* convert intel style 'long' variable to host format */
  284. {
  285.    char *charp = (char *)longp;
  286.    char temp[4];
  287.  
  288.    temp[3] = charp[0];
  289.    temp[2] = charp[1];
  290.    temp[1] = charp[2];
  291.    temp[0] = charp[3];
  292.  
  293.    charp[0] = temp[0];
  294.    charp[1] = temp[1];
  295.    charp[2] = temp[2];
  296.    charp[3] = temp[3];
  297. }
  298.  
  299. #endif
  300.  
  301.  
  302. /* ------------------------------------------------------------- */
  303.  
  304. void         skip_csize(void)
  305. {
  306.    lseek(zipfd,csize,SEEK_CUR);
  307.    zipeof = 1;
  308.    csize = 0L;
  309.    incnt = 0;
  310. }
  311.  
  312.  
  313. /* ------------------------------------------------------------- */
  314.  
  315. void         ReadByte(int *       x)
  316. {
  317.    if (incnt == 0)
  318.    {
  319.       if (csize == 0L)
  320.       {
  321.          zipeof = 1;
  322.          return;
  323.       }
  324.  
  325.       inpos = sizeof(inbuf);
  326.       if (inpos > csize)
  327.          inpos = (int)csize;
  328.       incnt = read(zipfd,inbuf,inpos);
  329.  
  330.       inpos = 1;
  331.       csize -= incnt;
  332.    }
  333.  
  334.    *x = inbuf[inpos-1];
  335.    inpos++;
  336.    incnt--;
  337. }
  338.  
  339.  
  340. /* ------------------------------------------------------------- */
  341.  
  342. void         ReadBits(int      bits,
  343.                       int *    x)
  344.      /* read the specified number of bits */
  345. {
  346.    int      bit;
  347.    int      bitv;
  348.  
  349.    *x = 0;
  350.    bitv = 1;
  351.  
  352.    for (bit = 0; bit <= bits-1; bit++)
  353.    {
  354.  
  355.       if (pcbits > 0)
  356.       {
  357.          pcbits--;
  358.          pcbitv = pcbitv << 1;  /* non intel: multiply by 2 */
  359.       }
  360.       else
  361.  
  362.       {
  363.          ReadByte(&pc);
  364.          pcbits = 7;
  365.          pcbitv = 1;
  366.       }
  367.  
  368.       if ((pc & pcbitv) != 0)
  369.          *x = *x | bitv;
  370.  
  371.       bitv = bitv << 1;         /* non intel: multiply by 2 */
  372.    }
  373.  
  374. }
  375.  
  376.  
  377. /* ---------------------------------------------------------- */
  378.  
  379. void         get_string(int      len,
  380.                         char *   s)
  381. {
  382.    read(zipfd,s,len);
  383.    s[len] = 0;
  384. }
  385.  
  386.  
  387. /* ------------------------------------------------------------- */
  388.  
  389. void         OutByte(int      c)
  390.    /* output each character from archive to screen */
  391. {
  392.    outbuf[outcnt /* outpos % sizeof(outbuf) */] = c;
  393.    outpos++;
  394.    outcnt++;
  395.  
  396.    if (outcnt == sizeof(outbuf))
  397.    {
  398.       write(outfd,outbuf,outcnt);
  399.       outcnt = 0;
  400.       printf(".");
  401.    }
  402. }
  403.  
  404.  
  405. /* ----------------------------------------------------------- */
  406.  
  407. int         reduce_L(int         x)
  408.    {
  409.       switch (factor) {
  410.          case 1:   return x & 0x7f;
  411.          case 2:   return x & 0x3f;
  412.          case 3:   return x & 0x1f;
  413.          case 4:   return x & 0x0f;
  414.       }
  415.     return 0; /* error */
  416.    }
  417.  
  418.  
  419. int         reduce_F(int         x)
  420.    {
  421.       switch (factor) {
  422.          case 1:   if (x == 127) return 2;  else return 3;
  423.          case 2:   if (x == 63) return 2;   else return 3;
  424.          case 3:   if (x == 31) return 2;   else return 3;
  425.          case 4:   if (x == 15) return 2;   else return 3;
  426.       }
  427.     return 0; /* error */
  428.    }
  429.  
  430.  
  431. int         reduce_D(int         x,
  432.                      int         y)
  433.    {
  434.       switch (factor) {
  435.          case 1:   return ((x >> 7) & 0x01) * 256 + y + 1;
  436.          case 2:   return ((x >> 6) & 0x03) * 256 + y + 1;
  437.          case 3:   return ((x >> 5) & 0x07) * 256 + y + 1;
  438.          case 4:   return ((x >> 4) & 0x0f) * 256 + y + 1;
  439.       }
  440.     return 0; /* error */
  441.    }
  442.  
  443.  
  444. int         reduce_B(int         x)
  445.         /* number of bits needed to encode the specified number */
  446.    {
  447.       switch (x - 1) {
  448.  
  449.          case 0:
  450.          case 1:   return 1;
  451.  
  452.          case 2:
  453.          case 3:   return 2;
  454.  
  455.          case 4:
  456.          case 5:
  457.          case 6:
  458.          case 7:   return 3;
  459.  
  460.          case 8:
  461.          case 9:
  462.          case 10:
  463.          case 11:
  464.          case 12:
  465.          case 13:
  466.          case 14:
  467.          case 15:   return 4;
  468.  
  469.          case 16:
  470.          case 17:
  471.          case 18:
  472.          case 19:
  473.          case 20:
  474.          case 21:
  475.          case 22:
  476.          case 23:
  477.          case 24:
  478.          case 25:
  479.          case 26:
  480.          case 27:
  481.          case 28:
  482.          case 29:
  483.          case 30:
  484.          case 31:   return 5;
  485.  
  486.          case 32:
  487.          case 33:
  488.          case 34:
  489.          case 35:
  490.          case 36:
  491.          case 37:
  492.          case 38:
  493.          case 39:
  494.          case 40:
  495.          case 41:
  496.          case 42:
  497.          case 43:
  498.          case 44:
  499.          case 45:
  500.          case 46:
  501.          case 47:
  502.          case 48:
  503.          case 49:
  504.          case 50:
  505.          case 51:
  506.          case 52:
  507.          case 53:
  508.          case 54:
  509.          case 55:
  510.          case 56:
  511.          case 57:
  512.          case 58:
  513.          case 59:
  514.          case 60:
  515.          case 61:
  516.          case 62:
  517.          case 63:   return 6;
  518.  
  519.          case 64:
  520.          case 65:
  521.          case 66:
  522.          case 67:
  523.          case 68:
  524.          case 69:
  525.          case 70:
  526.          case 71:
  527.          case 72:
  528.          case 73:
  529.          case 74:
  530.          case 75:
  531.          case 76:
  532.          case 77:
  533.          case 78:
  534.          case 79:
  535.          case 80:
  536.          case 81:
  537.          case 82:
  538.          case 83:
  539.          case 84:
  540.          case 85:
  541.          case 86:
  542.          case 87:
  543.          case 88:
  544.          case 89:
  545.          case 90:
  546.          case 91:
  547.          case 92:
  548.          case 93:
  549.          case 94:
  550.          case 95:
  551.          case 96:
  552.          case 97:
  553.          case 98:
  554.          case 99:
  555.          case 100:
  556.          case 101:
  557.          case 102:
  558.          case 103:
  559.          case 104:
  560.          case 105:
  561.          case 106:
  562.          case 107:
  563.          case 108:
  564.          case 109:
  565.          case 110:
  566.          case 111:
  567.          case 112:
  568.          case 113:
  569.          case 114:
  570.          case 115:
  571.          case 116:
  572.          case 117:
  573.          case 118:
  574.          case 119:
  575.          case 120:
  576.          case 121:
  577.          case 122:
  578.          case 123:
  579.          case 124:
  580.          case 125:
  581.          case 126:
  582.          case 127:   return 7;
  583.  
  584.       default:       return 8;
  585.       }
  586.    }
  587.  
  588.  
  589.  
  590. /* ----------------------------------------------------------- */
  591.  
  592. void         Expand(int      c)
  593.    {
  594.       #define DLE           144
  595.  
  596.       switch (ExState) {
  597.  
  598.            case 0:
  599.                if (c != DLE)
  600.                    OutByte(c);
  601.                else
  602.                    ExState = 1;
  603.            break;
  604.  
  605.            case 1:
  606.                if (c != 0)
  607.                {
  608.                    V = c;
  609.                    Len = reduce_L(V);
  610.                    ExState = reduce_F(Len);
  611.                }
  612.                else
  613.                {
  614.                    OutByte(DLE);
  615.                    ExState = 0;
  616.                }
  617.            break;
  618.  
  619.            case 2:   {
  620.                   Len = Len + c;
  621.                   ExState = 3;
  622.                }
  623.            break;
  624.  
  625.            case 3:   {
  626.                   int i;
  627.                   longint offset = reduce_D(V,c);
  628.                   longint op = outpos - offset;
  629.  
  630.                   for (i = 0; i <= Len + 2; i++)
  631.                   {
  632.                      if (op < 0L)
  633.                         OutByte(0);
  634.                      else
  635.                         OutByte(outbuf[(int)(op % sizeof(outbuf))]);
  636.                      op++;
  637.                   }
  638.  
  639.                   ExState = 0;
  640.                }
  641.          break;
  642.       }
  643.    }
  644.  
  645.  
  646. /* ----------------------------------------------------------- */
  647.  
  648. void         LoadFollowers(void)
  649.    {
  650.       int      x;
  651.       int      i;
  652.       int      b;
  653.  
  654.       for (x = 255; x >= 0; x--)
  655.       {
  656.          ReadBits(6,&b);
  657.          Slen[x] = b;
  658.  
  659.          for (i = 0; i < Slen[x]; i++)
  660.          {
  661.             ReadBits(8,&b);
  662.             followers[x][i] = b;
  663.          }
  664.       }
  665.    }
  666.  
  667.  
  668.  
  669. /* ----------------------------------------------------------- */
  670.  
  671. /*
  672.  * The Reducing algorithm is actually a combination of two
  673.  * distinct algorithms.  The first algorithm compresses repeated
  674.  * byte sequences, and the second algorithm takes the compressed
  675.  * stream from the first algorithm and applies a probabilistic
  676.  * compression method.
  677.  *
  678.  */
  679.  
  680. void         unReduce(void)
  681.      /* expand probablisticly reduced data */
  682.  
  683.    {
  684.  
  685.    int    lchar;
  686.    int    lout;
  687.    int    I;
  688.  
  689.    factor = cmethod - 1;
  690.    if ((factor < 1) || (factor > 4))
  691.    {
  692.       skip_csize();
  693.       return;
  694.    }
  695.  
  696.    ExState = 0;
  697.    LoadFollowers();
  698.    lchar =  0;
  699.  
  700.    while ((!zipeof) && (outpos < cusize))
  701.    {
  702.  
  703.       if (Slen[lchar] == 0)
  704.          ReadBits(8,&lout);
  705.       else
  706.  
  707.       {
  708.          ReadBits(1,&lout);
  709.          if (lout != 0)
  710.             ReadBits(8,&lout);
  711.          else
  712.          {
  713.             ReadBits(reduce_B(Slen[lchar]),&I);
  714.             lout = followers[lchar][I];
  715.          }
  716.       }
  717.  
  718.       Expand(lout);
  719.       lchar = lout;
  720.    }
  721. }
  722.  
  723.  
  724. /* ------------------------------------------------------------- */
  725. /*
  726.  * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
  727.  * with partial clearing.
  728.  *
  729.  */
  730.  
  731. void         partial_clear(void)
  732. {
  733.    int      pr;
  734.    int      cd;
  735.  
  736.  
  737.    /* mark all nodes as potentially unused */
  738.    for (cd = first_ent; cd < free_ent; cd++)
  739.       prefix_of[cd] |= 0x8000;
  740.  
  741.  
  742.    /* unmark those that are used by other nodes */
  743.    for (cd = first_ent; cd < free_ent; cd++)
  744.    {
  745.       pr = prefix_of[cd] & 0x7fff;   /* reference to another node? */
  746.       if (pr >= first_ent)           /* flag node as referenced */
  747.          prefix_of[pr] &= 0x7fff;
  748.    }
  749.  
  750.  
  751.    /* clear the ones that are still marked */
  752.    for (cd = first_ent; cd < free_ent; cd++)
  753.       if ((prefix_of[cd] & 0x8000) != 0)
  754.          prefix_of[cd] = -1;
  755.  
  756.  
  757.    /* find first cleared node as next free_ent */
  758.    free_ent = first_ent;
  759.    while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1))
  760.       free_ent++;
  761. }
  762.  
  763.  
  764. /* ------------------------------------------------------------- */
  765.  
  766. void         unShrink(void)
  767.  
  768. {
  769.    int      stackp;
  770.    int      finchar;
  771.    int      code;
  772.    int      oldcode;
  773.    int      incode;
  774.  
  775.  
  776.    /* decompress the file */
  777.    maxcodemax = 1 << max_bits;
  778.    cbits = init_bits;
  779.    maxcode = (1 << cbits) - 1;
  780.    free_ent = first_ent;
  781.    offset = 0;
  782.    sizex = 0;
  783.  
  784.    for (code = maxcodemax; code > 255; code--)
  785.       prefix_of[code] = -1;
  786.  
  787.    for (code = 255; code >= 0; code--)
  788.    {
  789.       prefix_of[code] = 0;
  790.       suffix_of[code] = code;
  791.    }
  792.  
  793.    ReadBits(cbits,&oldcode);
  794.    if (zipeof) return;
  795.    finchar = oldcode;
  796.  
  797.    OutByte(finchar);
  798.  
  799.    stackp = 0;
  800.  
  801.    while ((!zipeof))
  802.    {
  803.       ReadBits(cbits,&code);
  804.       if (zipeof) return;
  805.  
  806.       while (code == clear)
  807.       {
  808.          ReadBits(cbits,&code);
  809.  
  810.          switch (code) {
  811.  
  812.             case 1:   {
  813.                   cbits++;
  814.                   if (cbits == max_bits)
  815.                      maxcode = maxcodemax;
  816.                   else
  817.                      maxcode = (1 << cbits) - 1;
  818.                }
  819.             break;
  820.  
  821.             case 2:
  822.                   partial_clear();
  823.             break;
  824.          }
  825.  
  826.          ReadBits(cbits,&code);
  827.          if (zipeof) return;
  828.       }
  829.  
  830.  
  831.       /* special case for KwKwK string */
  832.       incode = code;
  833.       if (prefix_of[code] == -1)
  834.       {
  835.          stack[stackp] = finchar;
  836.          stackp++;
  837.          code = oldcode;
  838.       }
  839.  
  840.  
  841.       /* generate output characters in reverse order */
  842.       while (code >= first_ent)
  843.       {
  844.          stack[stackp] = suffix_of[code];
  845.          stackp++;
  846.          code = prefix_of[code];
  847.       }
  848.  
  849.       finchar = suffix_of[code];
  850.       stack[stackp] = finchar;
  851.       stackp++;
  852.  
  853.  
  854.       /* and put them out in forward order */
  855.       while (stackp > 0)
  856.       {
  857.          stackp--;
  858.          OutByte(stack[stackp]);
  859.       }
  860.  
  861.  
  862.       /* generate new entry */
  863.       code = free_ent;
  864.       if (code < maxcodemax)
  865.       {
  866.          prefix_of[code] = oldcode;
  867.          suffix_of[code] = finchar;
  868.          while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1))
  869.             free_ent++;
  870.       }
  871.  
  872.  
  873.       /* remember previous code */
  874.       oldcode = incode;
  875.    }
  876.  
  877. }
  878.  
  879.  
  880. /* ---------------------------------------------------------- */
  881.  
  882. void         extract_member(void)
  883. {
  884.    int    b;
  885.  
  886.    pcbits = 0;
  887.    incnt = 0;
  888.    outpos = 0L;
  889.    outcnt = 0;
  890.    zipeof = 0;
  891.  
  892.    /* create the output file with READ and WRITE permissions */
  893.    if (create_output_file())
  894.       exit(1);
  895.  
  896.    switch (cmethod) {
  897.  
  898.       case 0:     /* stored */
  899.             {
  900.                printf(" Extract: %s ...",filename);
  901.                while ((!zipeof))
  902.                {
  903.                   ReadByte(&b);
  904.                   OutByte(b);
  905.                }
  906.             }
  907.       break;
  908.  
  909.       case 1:   {
  910.                printf("UnShrink: %s ...",filename);
  911.                unShrink();
  912.             }
  913.       break;
  914.  
  915.       case 2:
  916.       case 3:
  917.       case 4:
  918.       case 5:   {
  919.                printf("  Expand: %s ...",filename);
  920.                unReduce();
  921.             }
  922.       break;
  923.  
  924.       default: printf("Unknown compression method.");
  925.    }
  926.  
  927.  
  928.    /* write the last partial buffer, if any */
  929.    if (outcnt > 0)
  930.       write(outfd,outbuf,outcnt);
  931.  
  932.    /* set output file date and time */
  933.    set_file_time();
  934.  
  935.    close(outfd);
  936.    printf("  done.\n");
  937. }
  938.  
  939.  
  940. /* ---------------------------------------------------------- */
  941.  
  942. void         process_local_file_header(void)
  943. {
  944.    read(zipfd,&lrec,sizeof(lrec));
  945.  
  946. #ifdef HIGH_LOW
  947.    swap_bytes(&lrec.filename_length);
  948.    swap_bytes(&lrec.extra_field_length);
  949.    swap_lbytes(&lrec.compressed_size);
  950.    swap_lbytes(&lrec.uncompressed_size);
  951.    swap_bytes(&lrec.compression_method);
  952. #endif
  953.  
  954.    get_string(lrec.filename_length,filename);
  955.    get_string(lrec.extra_field_length,extra);
  956.    csize = lrec.compressed_size;
  957.    cusize = lrec.uncompressed_size;
  958.    cmethod = lrec.compression_method;
  959.    extract_member();
  960. }
  961.  
  962.  
  963. /* ---------------------------------------------------------- */
  964.  
  965. void         process_central_file_header(void)
  966. {
  967.    central_directory_file_header rec;
  968.    char filename[STRSIZ];
  969.    char extra[STRSIZ];
  970.    char comment[STRSIZ];
  971.  
  972.    read(zipfd,&rec,sizeof(rec));
  973.  
  974. #ifdef HIGH_LOW
  975.    swap_bytes(&rec.filename_length);
  976.    swap_bytes(&rec.extra_field_length);
  977.    swap_bytes(&rec.file_comment_length);
  978. #endif
  979.  
  980.    get_string(rec.filename_length,filename);
  981.    get_string(rec.extra_field_length,extra);
  982.    get_string(rec.file_comment_length,comment);
  983. }
  984.  
  985.  
  986. /* ---------------------------------------------------------- */
  987.  
  988. void         process_end_central_dir(void)
  989. {
  990.    end_central_dir_record rec;
  991.    char comment[STRSIZ];
  992.  
  993.    read(zipfd,&rec,sizeof(rec));
  994.  
  995. #ifdef HIGH_LOW
  996.    swap_bytes(&rec.zipfile_comment_length);
  997. #endif
  998.  
  999.    get_string(rec.zipfile_comment_length,comment);
  1000. }
  1001.  
  1002.  
  1003. /* ---------------------------------------------------------- */
  1004.  
  1005. void         process_headers(void)
  1006. {
  1007.    longint sig;
  1008.  
  1009.    while (1)
  1010.    {
  1011.       if (read(zipfd,&sig,sizeof(sig)) != sizeof(sig))
  1012.          return;
  1013.  
  1014. #ifdef HIGH_LOW
  1015.       swap_lbytes(&sig);
  1016. #endif
  1017.  
  1018.       if (sig == local_file_header_signature)
  1019.          process_local_file_header();
  1020.       else
  1021.  
  1022.       if (sig == central_file_header_signature)
  1023.          process_central_file_header();
  1024.       else
  1025.  
  1026.       if (sig == end_central_dir_signature)
  1027.       {
  1028.          process_end_central_dir();
  1029.          return;
  1030.       }
  1031.  
  1032.       else
  1033.       {
  1034.          printf("Invalid Zipfile Header\n");
  1035.          return;
  1036.       }
  1037.    }
  1038.  
  1039. }
  1040.  
  1041.  
  1042. /* ---------------------------------------------------------- */
  1043.  
  1044. void         extract_zipfile(void)
  1045. {
  1046.    /* open the zipfile for reading and in BINARY mode to prevent
  1047.       cr/lf translation, which would corrupt the bitstreams */
  1048.  
  1049.    if (open_input_file())
  1050.       exit(1);
  1051.  
  1052.    process_headers();
  1053.  
  1054.    close(zipfd);
  1055. }
  1056.  
  1057.  
  1058. /* ---------------------------------------------------------- */
  1059. /*
  1060.  * main program
  1061.  *
  1062.  */
  1063.  
  1064. void main(int argc, char **argv)
  1065. {
  1066.    printf("\n");
  1067.    printf("%s\n",version);
  1068.    printf("Courtesy of:  S.H.Smith  and  The Tool Shop BBS,  (602) 279-2673.\n");
  1069.    printf("\n");
  1070.  
  1071.    if (argc != 2)
  1072.    {
  1073.       printf("Usage:  UnZip FILE[.zip]\n");
  1074.       exit(0);
  1075.    }
  1076.  
  1077.    /* .ZIP default if none provided by user */
  1078.    strcpy(zipfn,argv[1]);
  1079.    if (strchr(zipfn,'.') == NULL)
  1080.       strcat(zipfn,".ZIP");
  1081.  
  1082.    extract_zipfile();
  1083.    exit(0);
  1084. }
  1085.  
  1086.